package cn.chenhuanming.shh.administer.intermediary.business.service;

import cn.chenhuanming.shh.administer.entity.jpa.*;
import cn.chenhuanming.shh.administer.repository.*;
import cn.chenhuanming.shh.administer.utils.AuthorityTool;
import org.jooq.DSLContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.time.LocalDateTime;
import java.util.List;

/**
 * Created by chenhuanming on 2017-07-27.
 *
 * @author chenhuanming
 */
@Service
public class HouseService {
    @Autowired
    HouseRepository houseRepository;

    @Autowired
    UserBrokerRepository userbrokerRepository;

    @Autowired
    DistrictRepository districtRepository;

    @Autowired
    EstateRepository estateRepository;

    @Autowired
    EstateBrokerRepository estateBrokerRepository;

    @Autowired
    DSLContext dslContext;

    public List<House> findHouse(House house) {

        ExampleMatcher matcher = ExampleMatcher.matching()
                .withIgnoreCase(true)
                .withMatcher("name", ExampleMatcher.GenericPropertyMatchers.contains());

        Example<House> example = Example.of(house, matcher);
        List<House> houses = houseRepository.findAll(example);
        return houses;
    }

    /**
     * 房源创建工作
     *
     * @param house
     */
    public void beforeCreate(House house) {
        //设置经纪人冗余信息
        UserBroker broker = userbrokerRepository.getOne(AuthorityTool.getPrincipal());
        house.setUserBroker(broker);
        house.setBrokerName(broker.getName());

        //检查片区是否存在
        if (house.getDistrict().getId() == null)
            throw new IllegalArgumentException("片区不能为空");
        else {
            District area = districtRepository.findOne(house.getDistrict().getId());
            if (!districtRepository.exists(area.getParent().getId()))
                throw new IllegalArgumentException("片区必须要区/镇");
            else {
                District city = area.getParent();
                house.setCityName(city.getName());
                house.setCityAreaName(area.getName());
            }
        }

        //检查楼盘是否合法
        if (!estateRepository.exists(house.getEstate().getId())) {
            throw new IllegalArgumentException("楼盘不存在");
        } else {
            Estate estate = estateRepository.getOne(house.getEstate().getId());
            EstateBroker estateBroker = estateBrokerRepository.findByBrokerIdAndEstateId(broker.getUsername(), estate.getId());
            if (estateBroker == null)
                throw new IllegalStateException("你不拥有此楼盘权限");
            else {
                house.setEstateName(estate.getName());
            }
        }

        //设置创建时间
        house.setCreateTime(LocalDateTime.now());
        house.setIsQuality("否");
        house.setStatus("在租售");
    }


    /**
     * 动态查询
     * @return
     */
    public Specification<House> findHouseBySpecification(String type,
            String name, String cityName, String cityAreaName,
            Float lowArea, Float highArea,
            Float lowPrice, Float highPrice,
            String isQuality, String isAnxious, String isRecommended, String sortType, String sortBy) {
        return new Specification<House>() {
            @Override
            public Predicate toPredicate(Root<House> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Predicate predicates = cb.conjunction();
                if (!StringUtils.isEmpty(type)) {
                    predicates.getExpressions().add(cb.equal(root.get("type"), type));
                }
                if (!StringUtils.isEmpty(name)) {
                    predicates.getExpressions().add(cb.like(root.get("name"),"%" + name + "%"));
                }
                if (!StringUtils.isEmpty(cityAreaName)) {
                    predicates.getExpressions().add(cb.equal(root.get("cityAreaName"), cityAreaName));
                }
                if (!StringUtils.isEmpty(cityName)) {
                    predicates.getExpressions().add(cb.equal(root.get("cityName"), cityName));
                }
                if (!StringUtils.isEmpty(isQuality)) {
                    predicates.getExpressions().add(cb.equal(root.get("isQuality"), isQuality));
                }
                if (!StringUtils.isEmpty(isAnxious)) {
                    predicates.getExpressions().add(cb.equal(root.get("isAnxious"), isAnxious));
                }
                if (!StringUtils.isEmpty(isRecommended)) {
                    predicates.getExpressions().add(cb.equal(root.get("isRecommended"), isRecommended));
                }
                if (!StringUtils.isEmpty(lowArea)) {
                    predicates.getExpressions().add(cb.lessThanOrEqualTo(root.get("area"), lowArea));
                }
                if (!StringUtils.isEmpty(highArea)) {
                    predicates.getExpressions().add(cb.greaterThanOrEqualTo(root.get("area"), highArea));
                }
                if (!StringUtils.isEmpty(lowPrice)) {
                    predicates.getExpressions().add(cb.lessThanOrEqualTo(root.get("price"), lowPrice));
                }
                if (!StringUtils.isEmpty(highPrice)) {
                    predicates.getExpressions().add(cb.greaterThanOrEqualTo(root.get("price"),highPrice));
                }
                query.where(predicates);
                if (!StringUtils.isEmpty(sortType) && !StringUtils.isEmpty(sortBy)) {
                    if (sortType.equals("desc"))
                        query.orderBy(cb.desc(root.get(sortBy)));
                    if (sortType.equals("asc"))
                        query.orderBy(cb.asc(root.get(sortBy)));
                }
                if (sortBy == null || !sortBy.equals("createTime"))
                    query.orderBy(cb.desc(root.get("createTime")));
                return query.getRestriction();
            }
        };
    }
}